'use strict';

/**
 * Module dependencies.
 */
var _ = require('lodash'),
    defaultAssets = require('./config/assets/default'),
    testAssets = require('./config/assets/test'),
    testConfig = require('./config/env/test'),
    fs = require('fs'),
    path = require('path');

module.exports = function(grunt) {
    // Project Configuration
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        env: {
            test: {
                NODE_ENV: 'test'
            },
            dev: {
                NODE_ENV: 'development'
            },
            prod: {
                NODE_ENV: 'production'
            }
        },
        watch: {
            serverViews: {
                files: defaultAssets.server.views,
                options: {
                    livereload: true
                }
            },
            serverJS: {
                files: _.union(defaultAssets.server.gruntConfig, defaultAssets.server.allJS),
                //tasks: ['jshint'],
                options: {
                    livereload: true
                }
            },
            clientViews: {
                files: defaultAssets.client.views,
                options: {
                    livereload: true
                }
            },
            clientJS: {
                files: defaultAssets.client.js,
                //tasks: ['jshint'],
                options: {
                    livereload: true
                }
            },
            clientCSS: {
                files: defaultAssets.client.css,
                //tasks: ['csslint'],
                options: {
                    livereload: true
                }
            },
            clientSCSS: {
                files: defaultAssets.client.sass,
                tasks: ['sass', 'csslint'],
                options: {
                    livereload: true
                }
            },
            clientLESS: {
                files: defaultAssets.client.less,
                tasks: ['less', 'csslint'],
                options: {
                    livereload: true
                }
            }
        },
        nodemon: {
            dev: {
                script: 'server.js',
                options: {
                    nodeArgs: ['--debug'],
                    ext: 'js,html',
                    watch: _.union(defaultAssets.server.gruntConfig, defaultAssets.server.views, defaultAssets.server.allJS, defaultAssets.server.config)
                }
            }
        },
        concurrent: {
            default: ['nodemon', 'watch'],
            debug: ['nodemon', 'watch', 'node-inspector'],
            options: {
                logConcurrentOutput: true
            }
        },
        jshint: {
            all: {
                src: _.union(defaultAssets.server.gruntConfig, defaultAssets.server.allJS, defaultAssets.client.js, testAssets.tests.server, testAssets.tests.client, testAssets.tests.e2e),
                options: {
                    jshintrc: true,
                    node: true,
                    mocha: true,
                    jasmine: true
                }
            }
        },
        eslint: {
            options: {},
            target: _.union(defaultAssets.server.gruntConfig, defaultAssets.server.allJS, defaultAssets.client.js, testAssets.tests.server, testAssets.tests.client, testAssets.tests.e2e)
        },
        csslint: {
            options: {
                csslintrc: '.csslintrc'
            },
            all: {
                src: defaultAssets.client.css
            }
        },
        // Compiles ES6 with Babel
        babel: {
            options: {
                //sourceMap: true,
                presets: ['es2015']
            },
            dist: {
                files: [{
                    expand: true,
                    src: defaultAssets.client.js,
                    dest: '.tmp'
                }, {
                    expand: true,
                    src: 'modules/*/server/**/*.js',
                    dest: '.tmp'
                }]
            }
        },
        ngAnnotate: {
            production: {
                files: {
                    '.tmp/app.js': [
                        '.tmp/modules/core/client/app/config.js',
                        '.tmp/modules/core/client/app/init.js',
                        '.tmp/modules/*/client/*.js',
                        '.tmp/modules/*/client/**/*.js'
                    ]
                }
            }
        },
        concat: {
            production: {
                files: {
                    '.tmp/lib.js': defaultAssets.client.lib.js
                }
            }
        },
        uglify: {
            production: {
                files: [{
                    expand: true,
                    cwd: '.tmp',
                    src: [
                        'modules/Base/server/**/*.js',
                        'modules/Common/server/**/*.js',
                        'modules/SystemManage/server/**/*.js',
                        'modules/User/server/**/*.js'
                    ],
                    dest: 'dist'
                }, {
                    'dist/server.js': 'server.js',
                    'dist/public/www/js/vendor.js': '.tmp/lib.js',
                    'dist/public/www/js/scripts.js': '.tmp/app.js'
                }, {
                    'dist/public/www/js/tpls.js': '.tmp/templateCache.js'
                }]
            }
        },
        cssmin: {
            combine: {
                files: {
                    'dist/public/www/css/vendor.css': defaultAssets.client.lib.css,
                    'dist/public/www/css/main.css': defaultAssets.client.css
                }
            }
        },
        'node-inspector': {
            custom: {
                options: {
                    'web-port': 1337,
                    'web-host': 'localhost',
                    'debug-port': 5858,
                    'save-live-edit': true,
                    'no-preload': true,
                    'stack-trace-limit': 50,
                    'hidden': []
                }
            }
        },
        clean: {
            release: {
                files: [{
                    dot: true,
                    src: [
                        '.tmp',
                        'dist'
                    ]
                }]
            }
        },
        copy: {
            localConfig: {
                src: 'config/env/local.example.js',
                dest: 'config/env/local-development.js',
                filter: function() {
                    return !fs.existsSync('config/env/local-development.js');
                }
            },
            release: {
                files: [{
                    expand: true,
                    cwd: '.tmp',
                    src: 'modules/*/server/**/*.js',
                    dest: 'dist'
                }, {
                    expand: true,
                    dot: true,
                    cwd: 'public/lib/bootstrap/dist',
                    src: 'fonts/*',
                    dest: 'dist/public/www'
                }, {
                    expand: true,
                    dot: true,
                    src: [
                        'config/**/*.js',
                        'modules/*/client/Images/**/*', 
                        'modules/*/client/img/**/*',
                        'modules/core/server/views/{,*/}*.html',
                        'modules/core/server/views/{,*/}*.html',
                        'logs/**/*.log',
                        'README.md',
                        'package.json'
                    ],
                    dest: 'dist'
                }]
            }
        },
        ngtemplates: {
            dist: {
                options: {
                    module: 'Gateway'
                },
                src: 'modules/*/client/views/{,*/}*.html',
                dest: '.tmp/templateCache.js'
            }
        }
    });

    // Load NPM tasks
    require('load-grunt-tasks')(grunt);

    // Make sure upload directory exists
    grunt.task.registerTask('mkdir:upload', 'Task that makes sure upload directory exists.', function() {
        // Get the callback
        var done = this.async();

        grunt.file.mkdir(path.normalize(__dirname + '/modules/users/client/img/profile/uploads'));

        done();
    });

    // Make sure upload directory exists
    grunt.task.registerTask('mkdir:downloads', 'Task that makes sure upload directory exists.', function() {
        // Get the callback
        var done = this.async();

        grunt.file.mkdir(path.normalize(__dirname + '/dist/downloads'));

        done();
    });

    // Connect to the MongoDB instance and load the models
    grunt.task.registerTask('mongoose', 'Task that connects to the MongoDB instance and loads the application models.', function() {
        // Get the callback
        var done = this.async();

        // Use mongoose configuration
        var mongoose = require('./config/lib/mongoose.js');

        // Connect to database
        mongoose.connect(function(db) {
            done();
        });
    });

    // Drops the MongoDB database, used in e2e testing
    grunt.task.registerTask('dropdb', 'drop the database', function() {
        // async mode
        var done = this.async();

        // Use mongoose configuration
        var mongoose = require('./config/lib/mongoose.js');

        mongoose.connect(function(db) {
            db.connection.db.dropDatabase(function(err) {
                if (err) {
                    console.log(err);
                } else {
                    console.log('Successfully dropped db: ', db.connection.db.databaseName);
                }
                db.connection.db.close(done);
            });
        });
    });

    grunt.task.registerTask('server', 'Starting the server', function() {
        // Get the callback
        var done = this.async();

        var path = require('path');
        var app = require(path.resolve('./config/lib/app'));
        var server = app.start(function() {
            done();
        });
    });

    // Lint CSS and JavaScript files.
    //grunt.registerTask('lint', ['jshint', 'eslint', 'csslint']);

    // Lint project files and minify them into two production files.
    //grunt.registerTask('build', ['env:dev', 'ngAnnotate', 'uglify', 'cssmin']);

    // Run the project in development mode
    //grunt.registerTask('default', ['env:dev', 'lint', 'mkdir:upload', 'copy:localConfig', 'concurrent:default']);

    // Run the project in debug mode
    //grunt.registerTask('debug', ['env:dev', 'mkdir:upload', 'copy:localConfig', 'concurrent:debug']);

    // Run the project in production mode
    //grunt.registerTask('prod', ['build', 'env:prod', 'mkdir:upload', 'copy:localConfig', 'concurrent:default']);

    // Release the project
    grunt.registerTask('release', ['clean', 'ngtemplates', 'babel', 'ngAnnotate', 'concat', 'cssmin', 'copy:release', 'uglify', 'mkdir:downloads']);
};
